<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>期货量化研究报告展示</title>
    <!-- 引入 ECharts 库 -->
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
    <!-- 引入 Marked.js 用于解析 Markdown -->
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
    <!-- 引入 FontAwesome 用于图标 -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.2/css/all.min.css">
    
    <style>
        /* CSS样式部分保持不变，这里省略以节约篇幅。请使用上一版中的CSS代码。 */
        /* --- 1. 全局与变量定义 --- */
        :root {
            --bg-color: #f4f7f9;
            --sidebar-bg: #ffffff;
            --content-bg: #ffffff;
            --text-color: #333333;
            --text-color-secondary: #666666;
            --border-color: #e4e7ed;
            --primary-color: #409eff;
            --primary-color-light: #ecf5ff;
            --header-height: 60px;
            --sidebar-width: 260px;
            --toc-width: 220px;
        }

        .dark-theme {
            --bg-color: #141414;
            --sidebar-bg: #1d1d1d;
            --content-bg: #1d1d1d;
            --text-color: #e0e0e0;
            --text-color-secondary: #a0a0a0;
            --border-color: #3a3a3a;
            --primary-color: #2a7fdb;
            --primary-color-light: #28334a;
        }

        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
            background-color: var(--bg-color);
            color: var(--text-color);
            transition: background-color 0.3s, color 0.3s;
            overflow-x: hidden;
        }

        /* --- 2. 页面布局 --- */
        .app-layout {
            display: grid;
            grid-template-columns: var(--sidebar-width) 1fr var(--toc-width);
            grid-template-rows: var(--header-height) 1fr;
            grid-template-areas:
                "header header header"
                "sidebar content toc";
            height: 100vh;
        }

        .app-header { grid-area: header; }
        .app-sidebar { grid-area: sidebar; }
        .main-content { grid-area: content; }
        .table-of-contents { grid-area: toc; }

        /* --- 3. 组件样式 --- */
        /* 页头 */
        .app-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 0 24px;
            border-bottom: 1px solid var(--border-color);
            background-color: var(--sidebar-bg);
            transition: background-color 0.3s, border-color 0.3s;
            z-index: 100;
        }
        .app-header .logo { font-size: 20px; font-weight: 600; }
        .app-header .theme-switcher {
            font-size: 20px;
            cursor: pointer;
            color: var(--text-color-secondary);
        }

        /* 侧边栏 */
        .app-sidebar {
            background-color: var(--sidebar-bg);
            padding: 20px 0;
            border-right: 1px solid var(--border-color);
            overflow-y: auto;
            transition: background-color 0.3s, border-color 0.3s;
        }
        .menu-group .menu-title {
            padding: 12px 20px;
            font-size: 16px;
            font-weight: 500;
            cursor: pointer;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .menu-group .menu-title:hover { background-color: var(--bg-color); }
        .menu-group .menu-title .icon { transition: transform 0.3s; }
        .menu-group.open .menu-title .icon { transform: rotate(90deg); }
        
        .menu-items {
            max-height: 0;
            overflow: hidden;
            transition: max-height 0.3s ease-in-out;
        }
        .menu-group.open .menu-items { max-height: 500px; /* 一个足够大的值 */ }
        
        .menu-items .item {
            display: block;
            padding: 10px 20px 10px 40px;
            font-size: 14px;
            color: var(--text-color-secondary);
            text-decoration: none;
        }
        .menu-items .item:hover { color: var(--primary-color); }
        .menu-items .item.active {
            background-color: var(--primary-color-light);
            color: var(--primary-color);
            font-weight: 500;
        }

        /* 主内容区 */
        .main-content {
            overflow-y: auto;
            padding: 32px;
            background-color: var(--bg-color);
        }
        #report-container {
            max-width: 800px;
            margin: 0 auto;
            background-color: var(--content-bg);
            padding: 40px;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.05);
            transition: background-color 0.3s;
        }
        /* Markdown 渲染样式 */
        #report-content h1, #report-content h2, #report-content h3 {
            border-bottom: 1px solid var(--border-color);
            padding-bottom: 0.3em;
            margin-top: 24px;
            margin-bottom: 16px;
        }
        #report-content h1 { font-size: 2em; }
        #report-content h2 { font-size: 1.5em; }
        #report-content h3 { font-size: 1.25em; }
        #report-content p { line-height: 1.8; margin-bottom: 1em; }
        #report-content ul, #report-content ol { padding-left: 2em; }
        #report-content li { margin-bottom: 0.5em; }
        #report-content code {
            background-color: var(--bg-color);
            padding: .2em .4em;
            margin: 0;
            font-size: 85%;
            border-radius: 3px;
        }
        #report-content blockquote {
            padding: 0 1em;
            color: var(--text-color-secondary);
            border-left: 0.25em solid var(--border-color);
            margin-left: 0;
        }
        /* ECharts 容器 */
        .echart-placeholder {
            width: 100%;
            height: 450px;
            margin: 2rem 0;
            border-radius: 8px;
            border: 1px solid var(--border-color);
        }

        /* 目录 */
        .table-of-contents {
            padding: 20px;
            overflow-y: auto;
        }
        .toc-title {
            font-size: 16px;
            font-weight: 600;
            margin-bottom: 16px;
        }
        .toc-list { list-style: none; }
        .toc-list a {
            display: block;
            padding: 8px 0;
            color: var(--text-color-secondary);
            text-decoration: none;
            font-size: 14px;
            border-left: 2px solid transparent;
            padding-left: 12px;
            transition: all 0.2s;
        }
        .toc-list a:hover { color: var(--primary-color); }
        .toc-list a.active {
            color: var(--primary-color);
            border-left-color: var(--primary-color);
            font-weight: 500;
            transform: scale(1.02);
        }
        .toc-list .toc-h3 { padding-left: 24px; }


        /* --- 4. 响应式设计 --- */
        .mobile-menu-toggle {
            display: none;
            font-size: 20px;
            cursor: pointer;
        }

        @media (max-width: 1200px) {
            .app-layout {
                grid-template-columns: var(--sidebar-width) 1fr;
                grid-template-areas:
                    "header header"
                    "sidebar content";
            }
            .table-of-contents { display: none; } /* 在中等屏幕隐藏目录 */
        }

        @media (max-width: 768px) {
            .app-layout {
                grid-template-columns: 1fr;
                grid-template-areas:
                    "header"
                    "content";
            }
            .mobile-menu-toggle { display: block; }
            .app-sidebar {
                position: fixed;
                left: 0;
                top: 0;
                height: 100%;
                transform: translateX(-100%);
                transition: transform 0.3s ease-in-out;
                z-index: 200;
                width: 280px;
                border-right: 1px solid var(--border-color);
            }
            .app-sidebar.open {
                transform: translateX(0);
                box-shadow: 0 0 20px rgba(0,0,0,0.2);
            }
            .overlay {
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background-color: rgba(0,0,0,0.4);
                z-index: 199;
                opacity: 0;
                pointer-events: none;
                transition: opacity 0.3s;
            }
            .overlay.active {
                opacity: 1;
                pointer-events: auto;
            }
            #report-container {
                padding: 20px;
            }
        }
    </style>
</head>
<body class="dark-theme">

    <div class="app-layout">
        <!-- HTML结构部分保持不变，这里省略。请使用上一版中的HTML代码。 -->
        <header class="app-header">
            <div class="logo">
                <i class="fa-solid fa-bars mobile-menu-toggle"></i>
                <span style="margin-left: 15px;">期货量化研究报告</span>
            </div>
            <div class="theme-switcher">
                <i class="fa-solid fa-sun"></i>
            </div>
        </header>

        <aside class="app-sidebar">
            <div class="menu-group open"> <!-- 默认打开第一个 -->
                <div class="menu-title">
                    <span><i class="fa-solid fa-chart-line" style="margin-right: 8px;"></i>螺纹钢</span>
                    <i class="fa-solid fa-chevron-right icon"></i>
                </div>
                <div class="menu-items">
                    <a href="#" class="item active" data-report-id="rb2410-20231231">2023-12-31 报告</a>
                    <a href="#" class="item" data-report-id="rb2410-20231130">2023-11-30 报告</a>
                </div>
            </div>
            <div class="menu-group">
                <div class="menu-title">
                    <span><i class="fa-solid fa-mountain-sun" style="margin-right: 8px;"></i>铁矿石</span>
                    <i class="fa-solid fa-chevron-right icon"></i>
                </div>
                <div class="menu-items">
                    <a href="#" class="item" data-report-id="i2409-20231231">2023-12-31 报告</a>
                </div>
            </div>
             <div class="menu-group">
                <div class="menu-title">
                    <span><i class="fa-solid fa-gas-pump" style="margin-right: 8px;"></i>原油</span>
                    <i class="fa-solid fa-chevron-right icon"></i>
                </div>
                <div class="menu-items">
                    <a href="#" class="item" data-report-id="sc2408-20231231">2023-12-31 报告</a>
                </div>
            </div>
        </aside>

        <main class="main-content">
            <div id="report-container">
                <!-- 报告内容将由JS动态注入这里 -->
            </div>
        </main>

        <aside class="table-of-contents">
            <div class="toc-title">报告大纲</div>
            <ul class="toc-list" id="toc-list">
                <!-- 目录将由JS动态生成 -->
            </ul>
        </aside>
    </div>

    <div class="overlay"></div>
    
    <script id="mock-report-data" type="text/template">
        <!-- 报告模板部分保持不变，这里省略。请使用上一版中的报告模板代码。 -->
## 螺纹钢2410合约 量化投资策略报告 (数据截止: 2023-12-31)

### **一、 核心观点摘要 (Executive Summary)**
> 根据下文详细分析，我们观察到螺纹钢价格在分析周期内呈现先抑后扬的V型走势。初期受高库存压制，价格承压下行；后期随着库存的持续去化和宏观预期的改善，价格企稳回升。**核心驱动在于库存变化与价格呈现显著的负相关性**。当前库存处于低位，且价格已放量突破关键阻力位，短期策略建议**趋势看涨**。

### **二、 市场行情分析 (Market Analysis)**
#### **1. 价格趋势与波动性分析**
螺纹钢2410合约价格在2023年上半年主要在3500-3800区间震荡下行，并在6月初触及年度低点3450。随后，价格开始企稳反弹，形成清晰的上升通道。进入第四季度，价格上涨加速，成功突破了4000点的心理关口和前期高点，显示出较强的多头动能。

#### **2. 量价关系分析**
从下方的K线与成交量组合图可以看出，6月至8月的上涨伴随着成交量的温和放大，属于健康的“价涨量增”模式。10月后的加速上涨阶段，成交量显著放大，表明市场参与度提高，多头力量占据主导。年末价格在高位整理，成交量有所萎缩，可能预示短期有技术性回调需求。

#### **(图表1: K线与成交量组合图)**
```json
{
  "title": { "text": "螺纹钢2410 K线与成交量", "left": "center" },
  "tooltip": { "trigger": "axis", "axisPointer": { "type": "cross" } },
  "legend": { "data": ["K线", "成交量"], "top": "8%" },
  "grid": [ { "left": "10%", "right": "10%", "height": "50%" }, { "left": "10%", "right": "10%", "top": "65%", "height": "20%" } ],
  "xAxis": [
    { "type": "category", "data": ["2023-01-15", "2023-03-01", "2023-04-15", "2023-06-01", "2023-07-15", "2023-09-01", "2023-10-15", "2023-12-01", "2023-12-31"], "axisPointer": { "show": true } },
    { "type": "category", "gridIndex": 1, "data": ["2023-01-15", "2023-03-01", "2023-04-15", "2023-06-01", "2023-07-15", "2023-09-01", "2023-10-15", "2023-12-01", "2023-12-31"], "axisLabel": { "show": false } }
  ],
  "yAxis": [
    { "type": "value", "name": "价格", "scale": true },
    { "type": "value", "gridIndex": 1, "name": "成交量", "axisLabel": { "show": false } }
  ],
  "series": [
    { "name": "K线", "type": "candlestick", "data": [[4100, 4155, 4080, 4165], [3850, 3780, 3750, 3880], [3700, 3650, 3630, 3720], [3500, 3450, 3440, 3510], [3680, 3750, 3670, 3780], [3800, 3890, 3790, 3910], [3950, 4050, 3940, 4080], [4080, 4120, 4070, 4150], [4120, 4180, 4110, 4200]] },
    { "name": "成交量", "type": "bar", "xAxisIndex": 1, "yAxisIndex": 1, "data": [1650000, 2100000, 1900000, 2500000, 2200000, 2800000, 3500000, 2900000, 2600000] }
  ],
  "dataZoom": [ { "type": "inside", "xAxisIndex": [0, 1] }, { "show": true, "type": "slider", "top": "90%", "xAxisIndex": [0, 1] } ]
}
```

### **三、 基本面驱动因素分析 (Fundamental Analysis)**
#### **1. 关键基本面指标解读**
全国螺纹钢库存 (`inventory_10k_tons`) 是影响价格的核心基本面因素。年初库存处于高位，对价格形成压制。从第二季度开始，库存进入持续下降通道，表明下游需求复苏和钢厂主动去库，为价格上涨提供了坚实的基本面支撑。

#### **(图表2: 价格与关键基本面对比图)**
```json
{
  "title": { "text": "收盘价 vs 螺纹钢库存", "left": "center" },
  "tooltip": { "trigger": "axis" },
  "legend": { "data": ["收盘价", "库存(万吨)"], "top": "8%" },
  "grid": { "left": "10%", "right": "10%", "bottom": "15%" },
  "xAxis": { "type": "category", "data": ["2023-01-15", "2023-03-01", "2023-04-15", "2023-06-01", "2023-07-15", "2023-09-01", "2023-10-15", "2023-12-01", "2023-12-31"] },
  "yAxis": [
    { "type": "value", "name": "价格", "position": "left" },
    { "type": "value", "name": "库存", "position": "right", "inverse": true, "axisLabel": { "formatter": "{value} 万吨" } }
  ],
  "series": [
    { "name": "收盘价", "type": "line", "yAxisIndex": 0, "data": [4155, 3780, 3650, 3450, 3750, 3890, 4050, 4120, 4180], "smooth": true },
    { "name": "库存(万吨)", "type": "line", "yAxisIndex": 1, "data": [120, 155, 140, 110, 95, 80, 75, 70, 68], "smooth": true, "areaStyle": {} }
  ]
}
```

### **四、 量化关系探索 (Quantitative Correlation)**
#### **1. 价格与基本面相关性**
散点图清晰地揭示了螺纹钢收盘价与库存之间存在强烈的**负相关关系**。当库存高企时，价格普遍偏低；随着库存的下降，价格中枢明显上移。这符合供需理论：库存减少意味着供给相对紧张或需求旺盛，从而推高价格。

#### **(图表3: 价格与库存关系散点图)**
```json
{
    "title": { "text": "价格与库存关系散点图", "left": "center" },
    "grid": { "left": "10%", "right": "12%", "bottom": "10%", "top": "15%" },
    "xAxis": { "type": "value", "name": "库存 (万吨)", "splitLine": { "lineStyle": { "type": "dashed" } } },
    "yAxis": { "type": "value", "name": "收盘价", "splitLine": { "lineStyle": { "type": "dashed" } } },
    "series": [{
        "name": "价格-库存",
        "type": "scatter",
        "data": [[120, 4155], [155, 3780], [140, 3650], [110, 3450], [95, 3750], [80, 3890], [75, 4050], [70, 4120], [68, 4180]]
    }]
}
```
### **五、 投资策略构建 (Strategy Formulation)**
#### **1. 策略逻辑与触发条件**
- **入场条件 (做多)**: 当库存数据连续两周下降，且价格放量突破前40日高点时，建立多头头寸。
- **出场条件 (止盈/止损)**:
    - **止盈**: 目标位可设置为前期重要压力位或通道上轨。
    - **止损**: 当价格有效跌破20日移动平均线时，止损离场 (注: 本报告未提供均线数据，此为逻辑建议)。

#### **2. 策略历史回溯可视化**
根据上述逻辑，在历史数据中，一个理想的买入区间出现在**2023年9月初至10月末**。此期间，库存持续下降，且价格在9月初成功突破了7月的高点，随后开启了一波主升浪。

#### **(图表4: 策略信号可视化图)**
```json
{
  "title": { "text": "策略信号可视化", "subtext": "高亮区域为建议持有多头区间", "left": "center" },
  "tooltip": { "trigger": "axis" },
  "legend": { "data": ["收盘价", "库存(万吨)"], "top": "10%" },
  "xAxis": { "type": "category", "data": ["2023-01-15", "2023-03-01", "2023-04-15", "2023-06-01", "2023-07-15", "2023-09-01", "2023-10-15", "2023-12-01", "2023-12-31"] },
  "yAxis": { "type": "value", "name": "价格" },
  "series": [
    {
      "name": "收盘价", "type": "line", "data": [4155, 3780, 3650, 3450, 3750, 3890, 4050, 4120, 4180], "smooth": true,
      "markArea": {
        "itemStyle": { "color": "rgba(42, 127, 219, 0.2)" },
        "data": [
          [{ "name": "建议买入/持有多头区间", "xAxis": "2023-09-01" }, { "xAxis": "2023-10-15" }]
        ]
      }
    }
  ]
}
```

### **六、 风险提示 (Risk Disclosure)**
- 本报告完全基于历史数据进行分析，历史规律不代表未来走势，市场存在不确定性。
- 宏观政策（如房地产、基建政策）的突然转向，是影响螺纹钢需求的核心风险点，可能导致策略失效。
- 本报告不构成任何具体的投资建议，仅为量化分析与研究用途，投资者需自行承担风险。
    </script>
    
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // --- 1. DOM元素获取 ---
            const body = document.body;
            const themeSwitcher = document.querySelector('.theme-switcher');
            const themeIcon = themeSwitcher.querySelector('i');
            const sidebar = document.querySelector('.app-sidebar');
            const mobileMenuToggle = document.querySelector('.mobile-menu-toggle');
            const overlay = document.querySelector('.overlay');
            const reportContainer = document.getElementById('report-container');
            const mockReportData = document.getElementById('mock-report-data').textContent;
            const tocList = document.getElementById('toc-list');
            
            // --- 2. 状态变量 ---
            let chartConfigs = [];
            let renderedChartInstances = [];

            // --- 3. 函数定义 (所有函数在此处提前声明) ---

            /**
             * 渲染图表的核心函数
             */
            const renderCharts = () => {
                // 清理旧的图表实例
                renderedChartInstances.forEach(chart => chart.dispose());
                renderedChartInstances = [];

                const currentTheme = body.classList.contains('dark-theme') ? 'dark' : 'light';
                
                chartConfigs.forEach((option, index) => {
                    const chartDom = document.getElementById(`chart-container-${index}`);
                    if (chartDom) {
                        const chart = echarts.init(chartDom, currentTheme, { renderer: 'svg' });
                        chart.setOption(option);
                        renderedChartInstances.push(chart);
                    }
                });
            };
            
            /**
             * 应用主题
             */
            const applyTheme = (theme) => {
                if (theme === 'dark') {
                    body.classList.add('dark-theme');
                    body.classList.remove('light-theme');
                    themeIcon.className = 'fa-solid fa-moon';
                } else {
                    body.classList.add('light-theme');
                    body.classList.remove('dark-theme');
                    themeIcon.className = 'fa-solid fa-sun';
                }
                // 主题变化后，重新渲染所有图表以应用新主题
                renderCharts();
            };
            
            /**
             * 生成目录
             */
            const generateToc = () => {
                tocList.innerHTML = '';
                const headings = reportContainer.querySelectorAll('h2, h3');
                headings.forEach((h, index) => {
                    const id = `heading-${index}`;
                    h.id = id;
                    const link = document.createElement('a');
                    link.href = `#${id}`;
                    link.textContent = h.textContent.replace(/\([\s\S]*?\)/, '').trim(); // 移除括号内容
                    link.className = h.tagName === 'H3' ? 'toc-h3' : 'toc-h2';
                    
                    const listItem = document.createElement('li');
                    listItem.appendChild(link);
                    tocList.appendChild(listItem);
                });
                // 添加点击平滑滚动
                document.querySelectorAll('.toc-list a').forEach(anchor => {
                    anchor.addEventListener('click', function (e) {
                        e.preventDefault();
                        const targetElement = document.querySelector(this.getAttribute('href'));
                        if (targetElement) {
                             targetElement.scrollIntoView({ behavior: 'smooth' });
                        }
                    });
                });
            };
            
            /**
             * 目录滚动监听
             */
            const tocScrollSpy = () => {
                const headings = Array.from(reportContainer.querySelectorAll('h2, h3'));
                if(headings.length === 0) return;
                
                const observer = new IntersectionObserver(entries => {
                    entries.forEach(entry => {
                        const id = entry.target.getAttribute('id');
                        const tocLink = document.querySelector(`.toc-list a[href="#${id}"]`);
                        if (tocLink) {
                            if (entry.isIntersecting) {
                                document.querySelectorAll('.toc-list a').forEach(link => link.classList.remove('active'));
                                tocLink.classList.add('active');
                            }
                        }
                    });
                }, { rootMargin: "0px 0px -80% 0px" });

                headings.forEach(h => observer.observe(h));
            };

            /**
             * 解析并渲染报告
             */
            const parseAndRenderReport = (markdownContent) => {
                reportContainer.innerHTML = ''; // 清理旧内容
                
                // 重置图表配置
                chartConfigs = [];
                let chartIndex = 0;

                const htmlContent = markdownContent.replace(
                    /```json\s*([\s\S]*?)\s*```/g,
                    (match, jsonString) => {
                        try {
                            const option = JSON.parse(jsonString);
                            chartConfigs.push(option);
                            return `<div id="chart-container-${chartIndex++}" class="echart-placeholder"></div>`;
                        } catch (e) {
                            console.error("解析ECharts JSON失败:", e);
                            return `<div class="error">图表代码解析失败</div>`;
                        }
                    }
                );

                reportContainer.innerHTML = `<div id="report-content">${marked.parse(htmlContent)}</div>`;
                
                // DOM更新后，再渲染图表、生成目录和启动监听
                setTimeout(() => {
                    renderCharts();
                    generateToc();
                    tocScrollSpy();
                }, 0);
            };


            // --- 4. 事件监听与初始化 ---
            
            // 主题切换事件
            themeSwitcher.addEventListener('click', () => {
                const newTheme = body.classList.contains('dark-theme') ? 'light' : 'dark';
                localStorage.setItem('theme', newTheme);
                applyTheme(newTheme);
            });

            // 侧边栏手风琴事件
            document.querySelectorAll('.menu-group .menu-title').forEach(title => {
                title.addEventListener('click', () => {
                    title.parentElement.classList.toggle('open');
                });
            });

            // 移动端菜单事件
            mobileMenuToggle.addEventListener('click', () => {
                sidebar.classList.toggle('open');
                overlay.classList.toggle('active');
            });
            overlay.addEventListener('click', () => {
                sidebar.classList.remove('open');
                overlay.classList.remove('active');
            });

            // --- 5. 初始加载 ---
            // 初始化时应用保存的主题或系统偏好
            const savedTheme = localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
            // 先设置好主题class，再加载报告，这样图表第一次渲染就是正确的颜色
            if (savedTheme === 'dark') {
                body.classList.add('dark-theme');
                themeIcon.className = 'fa-solid fa-moon';
            } else {
                body.classList.add('light-theme');
                themeIcon.className = 'fa-solid fa-sun';
            }
            
            // 加载默认报告
            parseAndRenderReport(mockReportData);

        });
    </script>
</body>
</html>